#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) {% now 'utc', '%Y' %} {{ cookiecutter.full_name }}{% if cookiecutter.affiliation %} / {{ cookiecutter.affiliation }}{% endif %}. All rights reserved.
# SPDX-License-Identifier: {{ cookiecutter._license }}
#
# {{ cookiecutter.project_name }} CLI wrapper.
# Delegates to the standalone `holoscan-cli` package with module-specific
# defaults baked in, defaulting to NVIDIA PyPI release-candidate-capable
# install args.
#
# Usage:
#   ./holohub run-container
#   ./holohub build {{ cookiecutter.module_slug }}_pipeline
#   ./holohub run   {{ cookiecutter.module_slug }}_pipeline --language python
#   ./holohub --help
#
# Optional overrides (rarely needed):
#   HOLOSCAN_CLI_SOURCE   Local checkout — wins over the package install.
#   HOLOSCAN_CLI_INSTALL_ARGS  Pip install arguments.
#   HOLOSCAN_CLI_PYTHON_BIN  Caller-owned Python interpreter.
#   HOLOSCAN_CLI_VENV         Wrapper-managed venv location.

set -euo pipefail

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

# ==============================================================================
# Module identity — defaults consumed by holoscan-cli
# ==============================================================================

# HOLOSCAN_CLI_ROOT: the CLI uses this as the project root for cmake -S and container paths.
export HOLOSCAN_CLI_ROOT="${HOLOSCAN_CLI_ROOT:-${SCRIPT_DIR}}"
# HOLOSCAN_CLI_CMD_NAME: shown in help output and error messages.
export HOLOSCAN_CLI_CMD_NAME="${HOLOSCAN_CLI_CMD_NAME:-${BASH_SOURCE[0]}}"
# HOLOSCAN_CLI_REPO_PREFIX: base for naming build dirs, images, etc.
export HOLOSCAN_CLI_REPO_PREFIX="${HOLOSCAN_CLI_REPO_PREFIX:-{{ cookiecutter.module_slug }}}"
# HOLOSCAN_CLI_CONTAINER_PREFIX: Docker image name prefix.
export HOLOSCAN_CLI_CONTAINER_PREFIX="${HOLOSCAN_CLI_CONTAINER_PREFIX:-{{ cookiecutter.module_slug.replace('_', '-') }}}"
# HOLOSCAN_CLI_WORKSPACE_NAME: directory name inside the container at /workspace/.
export HOLOSCAN_CLI_WORKSPACE_NAME="${HOLOSCAN_CLI_WORKSPACE_NAME:-{{ cookiecutter.module_slug }}}"
# HOLOSCAN_CLI_HOSTNAME_PREFIX: container hostname prefix.
export HOLOSCAN_CLI_HOSTNAME_PREFIX="${HOLOSCAN_CLI_HOSTNAME_PREFIX:-{{ cookiecutter.module_slug.replace('_', '-') }}}"

# ==============================================================================
# Paths
# ==============================================================================

export HOLOSCAN_CLI_DEFAULT_DOCKERFILE="${HOLOSCAN_CLI_DEFAULT_DOCKERFILE:-${SCRIPT_DIR}/Dockerfile}"
# Recursive walk from working directory — picks up the top-level metadata.json
# (project_type=module) along with operators/<x>/metadata.json and
# applications/<y>/metadata.json. The narrower default
# `applications,operators` skipped the module's own descriptor, so
# `./holohub list` showed no MODULES section and `./holohub package
# <name>` couldn't find the module by name. (holohub#1582)
export HOLOSCAN_CLI_SEARCH_PATH="${HOLOSCAN_CLI_SEARCH_PATH:-./}"
export HOLOSCAN_CLI_BUILD_PARENT_DIR="${HOLOSCAN_CLI_BUILD_PARENT_DIR:-${SCRIPT_DIR}/build}"
export HOLOSCAN_CLI_DATA_DIR="${HOLOSCAN_CLI_DATA_DIR:-${SCRIPT_DIR}/data}"

# ==============================================================================
# Build defaults
# ==============================================================================

export CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}"

# ==============================================================================
# holoscan-cli bootstrap + exec
# ==============================================================================

export HOLOSCAN_CLI_INSTALL_ARGS="${HOLOSCAN_CLI_INSTALL_ARGS:---pre --extra-index-url https://pypi.nvidia.com holoscan-cli>4.2.0}"
# Single bump point for the CLI version everywhere (host, images, runtime);
# keep in sync with the HoloHub repo wrapper.
HOLOSCAN_CLI_DEFAULT_PIN="4.5.0"
export HOLOSCAN_CLI_PINNED_VERSION="${HOLOSCAN_CLI_PINNED_VERSION-${HOLOSCAN_CLI_DEFAULT_PIN}}"
CLI_VENV_EXPLICIT="${HOLOSCAN_CLI_VENV:+1}"
if [[ -z "${HOLOSCAN_CLI_VENV:-}" && -n "${XDG_DATA_HOME:-}${HOME:-}" ]]; then
    HOLOSCAN_CLI_VENV="${XDG_DATA_HOME:-${HOME}/.local/share}/holoscan-cli/venv"
fi
export HOLOSCAN_CLI_VENV="${HOLOSCAN_CLI_VENV:-}"

# Default Holoscan SDK version for this module's container base image.
# holoscan-cli decoupled the base image from its own version (holoscan-cli#177)
# and no longer ships a built-in default, so it errors unless this is set (or
# --base-img is passed). Defaults to the module's holoscan_version.
export HOLOSCAN_CLI_BASE_SDK_VERSION="${HOLOSCAN_CLI_BASE_SDK_VERSION:-{{ cookiecutter.holoscan_version }}}"

if [[ -n "${HOLOSCAN_CLI_SOURCE:-}" ]]; then
    export PYTHONPATH="${HOLOSCAN_CLI_SOURCE%/}/src${PYTHONPATH:+:${PYTHONPATH}}"
fi

_cli_ok() {
    local python="$1"
    if [[ -n "${HOLOSCAN_CLI_PINNED_VERSION}" && -z "${HOLOSCAN_CLI_SOURCE:-}" ]]; then
        [[ "$("${python}" -c 'from importlib.metadata import version; print(version("holoscan-cli"))' 2>/dev/null)" \
            == "${HOLOSCAN_CLI_PINNED_VERSION}" ]]
    else
        "${python}" -m holoscan_cli --help 2>/dev/null | grep -qw build
    fi
}
_is_container() {
    [[ -f /.dockerenv || -f /run/.containerenv || -f /run/systemd/container ]] ||
        grep -Eq '(docker|containerd|kubepods|podman|buildkit)' /proc/1/cgroup 2>/dev/null
}
_managed_venv_ready() {
    [[ -n "${HOLOSCAN_CLI_VENV}" && -x "${HOLOSCAN_CLI_VENV}/bin/python" ]] &&
        "${HOLOSCAN_CLI_VENV}/bin/python" -m pip --version >/dev/null 2>&1
}
_use_managed_venv() {
    if [[ -z "${HOLOSCAN_CLI_VENV}" ]]; then
        echo "[{{ cookiecutter.module_slug }}] Set HOME, XDG_DATA_HOME, or HOLOSCAN_CLI_VENV." >&2
        exit 1
    fi
    if ! python3 -m venv "${HOLOSCAN_CLI_VENV}"; then
        echo "[{{ cookiecutter.module_slug }}] Could not create ${HOLOSCAN_CLI_VENV}; install python3-venv." >&2
        exit 1
    fi
    PYTHON_BIN="${HOLOSCAN_CLI_VENV}/bin/python"
}

PYTHON_BIN="${HOLOSCAN_CLI_PYTHON_BIN:-${VIRTUAL_ENV:+$VIRTUAL_ENV/bin/python}}"
if [[ -z "${PYTHON_BIN}" ]]; then
    unset PYTHONHOME
fi
if [[ -n "${PYTHON_BIN}" ]]; then
    :
elif [[ "${EUID}" -eq 0 ]] && _is_container; then
    PYTHON_BIN="python3"
    export PIP_BREAK_SYSTEM_PACKAGES="${PIP_BREAK_SYSTEM_PACKAGES:-1}"
elif _managed_venv_ready; then
    PYTHON_BIN="${HOLOSCAN_CLI_VENV}/bin/python"
elif [[ -n "${CLI_VENV_EXPLICIT}" ]]; then
    _use_managed_venv
elif _is_container && [[ -z "${HOLOSCAN_CLI_SOURCE:-}" ]] && _cli_ok python3; then
    PYTHON_BIN="python3"
elif _is_container; then
    echo "[{{ cookiecutter.module_slug }}] This container lacks holoscan-cli" \
         "${HOLOSCAN_CLI_PINNED_VERSION:+==${HOLOSCAN_CLI_PINNED_VERSION}}; rebuild the image." >&2
    exit 1
else
    _use_managed_venv
fi

if ! _cli_ok "${PYTHON_BIN}"; then
    if ! "${PYTHON_BIN}" -m pip --version >/dev/null 2>&1; then
        "${PYTHON_BIN}" -m ensurepip --upgrade >/dev/null 2>&1 || {
            echo "[{{ cookiecutter.module_slug }}] ${PYTHON_BIN} has no pip and ensurepip is unavailable;" \
                 "install pip or set HOLOSCAN_CLI_PYTHON_BIN to an interpreter that has it" \
                 "and retry" >&2
            exit 1
        }
    fi
    if [[ -n "${HOLOSCAN_CLI_SOURCE:-}" ]]; then
        echo "[{{ cookiecutter.module_slug }}] installing holoscan-cli from ${HOLOSCAN_CLI_SOURCE}" >&2
        "${PYTHON_BIN}" -m pip install --upgrade "${HOLOSCAN_CLI_SOURCE}"
    else
        echo "[{{ cookiecutter.module_slug }}] installing with args: ${HOLOSCAN_CLI_INSTALL_ARGS}" >&2
        "${PYTHON_BIN}" -m pip install ${HOLOSCAN_CLI_INSTALL_ARGS} \
            ${HOLOSCAN_CLI_PINNED_VERSION:+"holoscan-cli==${HOLOSCAN_CLI_PINNED_VERSION}"} || {
            _is_container && echo "[{{ cookiecutter.module_slug }}] Install failed in this" \
                "container; rebuild the image (./holohub build-container)." >&2
            exit 1
        }
    fi
fi

# Containers re-enter through this mounted wrapper so the pinned CLI version
# is verified at runtime.
export HOLOSCAN_CLI_IN_CONTAINER_CMD="${HOLOSCAN_CLI_IN_CONTAINER_CMD:-./${BASH_SOURCE[0]##*/}}"

# exec so signals reach the CLI directly; `python -m` so the same interpreter
# that bootstrapped the CLI above runs it (a `holoscan` console script on PATH
# may resolve elsewhere).
exec "${PYTHON_BIN}" -m holoscan_cli "$@"
